package commands

import (
	"encoding/json"
	"fmt"
	"os"
	"text/tabwriter"
	"time"

	"github.com/spf13/cobra"
	client "github.com/yourusername/lvm-manager/pkg/client"
)

// SnapshotCommands returns a command object for snapshot management
// It does NOT take a client; instead, each subcommand creates its own client using the --api flag.
func SnapshotCommands() *cobra.Command {
	cmd := &cobra.Command{
		Use:     "snapshot",
		Short:   "Manage domain snapshots",
		Aliases: []string{"snap"},
	}

	cmd.AddCommand(
		snapshotListCmd(),
		snapshotGetCmd(),
		snapshotCreateCmd(),
		snapshotRevertCmd(),
		snapshotDeleteCmd(),
	)

	return cmd
}

// snapshotListCmd 列出指定 domain 的所有快照
func snapshotListCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:     "list <domain>",
		Short:   "List all snapshots for a domain",
		Aliases: []string{"ls"},
		Args:    cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(cmd)
			domainName := args[0]
			snapshots, err := apiClient.ListSnapshots(domainName)
			if err != nil {
				return fmt.Errorf("failed to list snapshots: %w", err)
			}

			// 表格输出
			w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
			fmt.Fprintln(w, "NAME\tDOMAIN\tSTATE\tCREATION TIME\tCURRENT\tDESCRIPTION")
			fmt.Fprintln(w, "----\t------\t-----\t-------------\t-------\t-----------")

			for _, s := range snapshots {
				current := "no"
				if s.IsCurrent {
					current = "yes"
				}

				creationTime := s.CreationTime.Format("2006-01-02 15:04:05")

				fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\n",
					s.Name, s.Domain, s.State, creationTime, current, s.Description)
			}
			w.Flush()

			fmt.Printf("\nTotal: %d snapshots\n", len(snapshots))
			return nil
		},
	}

	return cmd
}

// snapshotGetCmd 获取快照详情
func snapshotGetCmd() *cobra.Command {
	var outputJSON bool
	var includeXML bool

	cmd := &cobra.Command{
		Use:   "get <domain> <name>",
		Short: "Get snapshot details",
		Args:  cobra.ExactArgs(2),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(cmd)
			domainName := args[0]
			name := args[1]
			snapshot, err := apiClient.GetSnapshot(domainName, name)
			if err != nil {
				return fmt.Errorf("failed to get snapshot: %w", err)
			}

			if outputJSON {
				data, _ := json.MarshalIndent(snapshot, "", "  ")
				fmt.Println(string(data))
			} else {
				fmt.Printf("Name:          %s\n", snapshot.Name)
				fmt.Printf("Domain:        %s\n", snapshot.Domain)
				fmt.Printf("State:         %s\n", snapshot.State)
				fmt.Printf("Creation Time: %s\n", snapshot.CreationTime.Format(time.RFC3339))
				fmt.Printf("Current:       %v\n", snapshot.IsCurrent)
				fmt.Printf("Parent:        %s\n", snapshot.Parent)
				fmt.Printf("Description:   %s\n", snapshot.Description)

				if includeXML && snapshot.XMLConfig != "" {
					fmt.Printf("\nXML Configuration:\n%s\n", snapshot.XMLConfig)
				}
			}
			return nil
		},
	}

	cmd.Flags().BoolVarP(&outputJSON, "json", "j", false, "Output in JSON format")
	cmd.Flags().BoolVarP(&includeXML, "xml", "x", false, "Include XML configuration")
	return cmd
}

// snapshotCreateCmd 创建快照
func snapshotCreateCmd() *cobra.Command {
	var spec client.CreateSnapshotSpec

	cmd := &cobra.Command{
		Use:   "create <domain>",
		Short: "Create a new snapshot",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(cmd)
			domainName := args[0]
			snapshot, err := apiClient.CreateSnapshot(domainName, &spec)
			if err != nil {
				return fmt.Errorf("failed to create snapshot: %w", err)
			}

			fmt.Printf("Snapshot '%s' created successfully for domain '%s'\n", snapshot.Name, snapshot.Domain)
			return nil
		},
	}

	cmd.Flags().StringVar(&spec.Name, "name", "", "Snapshot name")
	cmd.Flags().StringVar(&spec.Description, "description", "", "Snapshot description")
	cmd.Flags().BoolVar(&spec.MemoryState, "memory", false, "Include memory state")
	cmd.Flags().BoolVar(&spec.DiskOnly, "disk-only", false, "Disk only snapshot")
	cmd.Flags().BoolVar(&spec.Quiesce, "quiesce", false, "Use guest agent to quiesce filesystem")
	cmd.Flags().BoolVar(&spec.Atomic, "atomic", false, "Atomic operation")

	return cmd
}

// snapshotRevertCmd 恢复到指定快照
func snapshotRevertCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "revert <domain> <name>",
		Short: "Revert domain to a snapshot",
		Args:  cobra.ExactArgs(2),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(cmd)
			domainName := args[0]
			name := args[1]

			if err := apiClient.RevertSnapshot(domainName, name); err != nil {
				return fmt.Errorf("failed to revert to snapshot: %w", err)
			}
			fmt.Printf("Domain '%s' reverted to snapshot '%s'\n", domainName, name)
			return nil
		},
	}
}

// snapshotDeleteCmd 删除快照
func snapshotDeleteCmd() *cobra.Command {
	return &cobra.Command{
		Use:     "delete <domain> <name>",
		Short:   "Delete a snapshot",
		Aliases: []string{"rm"},
		Args:    cobra.ExactArgs(2),
		RunE: func(cmd *cobra.Command, args []string) error {
			apiClient := getAPIClient(cmd)
			domainName := args[0]
			name := args[1]

			if err := apiClient.DeleteSnapshot(domainName, name); err != nil {
				return fmt.Errorf("failed to delete snapshot: %w", err)
			}
			fmt.Printf("Snapshot '%s' for domain '%s' deleted\n", name, domainName)
			return nil
		},
	}
}
